package model

import (
	"fmt"
	"new_for_deepseek_rabbitmq/config"
	"sync"
	"time"

	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
)

// 全局变量定义
var (
	instance *MySQL    // MySQL单例实例
	once     sync.Once // 确保只初始化一次的同步原语
)

// MySQL 结构体封装了数据库连接和并发控制
type MySQL struct {
	DB *gorm.DB     // gorm数据库实例
	mu sync.RWMutex // 读写锁，用于并发控制
}

// Config MySQL配置结构体
type MySQLConfig struct {
	Host         string        // 数据库主机地址
	Port         int           // 数据库端口
	User         string        // 数据库用户名
	Password     string        // 数据库密码
	DBName       string        // 数据库名称
	MaxIdleConns int           // 最大空闲连接数
	MaxOpenConns int           // 最大打开连接数
	MaxLifetime  time.Duration // 连接最大生命周期
}

// GetInstance 获取MySQL单例实例
// 返回MySQL实例指针
func GetInstance() *MySQL {
	if instance == nil {
		panic("MySQL instance is not initialized")
	}
	return instance
}

// Initialize 初始化MySQL连接
// @param cfg *Config MySQL配置信息
// @return error 初始化错误信息
func Initialize() error {

	//mysql配置
	mysqlConfig := MySQLConfig{
		Host:         config.DefaultConfig.Database.Host,                                     // 数据库主机
		Port:         config.DefaultConfig.Database.Port,                                     //数据库端口
		User:         config.DefaultConfig.Database.User,                                     // 数据库用户名
		Password:     config.DefaultConfig.Database.Password,                                 // 数据库密码
		DBName:       config.DefaultConfig.Database.Name,                                     //数据库名称
		MaxIdleConns: config.DefaultConfig.Database.MaxIdleConns,                             //最大空闲连接数
		MaxOpenConns: config.DefaultConfig.Database.MaxOpenConns,                             //最大打开连接数
		MaxLifetime:  time.Duration(config.DefaultConfig.Database.MaxLifetime) * time.Second, //连接最大生命周期
	}

	var err error
	once.Do(func() {
		instance = &MySQL{}
		err = instance.connect(mysqlConfig)
	})
	return err
}

// connect 建立MySQL连接
// @param cfg *MySQLConfig MySQL配置信息
// @return error 连接错误信息
func (m *MySQL) connect(cfg MySQLConfig) error {
	// 构建DSN连接字符串
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		cfg.User, cfg.Password, cfg.Host, cfg.Port, cfg.DBName)

	// 打开数据库连接
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info), // 启用日志
	})

	if err != nil {
		return fmt.Errorf("连接MySQL失败: %v", err)
	}

	// 获取底层SQL连接池
	sqlDB, err := db.DB()
	if err != nil {
		return fmt.Errorf("获取底层数据库连接失败: %v", err)
	}

	// 设置连接池参数
	sqlDB.SetMaxIdleConns(cfg.MaxIdleConns)   // 设置空闲连接池中的最大连接数
	sqlDB.SetMaxOpenConns(cfg.MaxOpenConns)   // 设置打开数据库连接的最大数量
	sqlDB.SetConnMaxLifetime(cfg.MaxLifetime) // 设置连接可复用的最大时间

	m.DB = db
	return nil
}

// GetDB 获取数据库连接实例
// 使用读锁保证并发安全
// @return *gorm.DB gorm数据库实例
func (m *MySQL) GetDB() *gorm.DB {
	m.mu.RLock()
	defer m.mu.RUnlock()
	return m.DB
}
